glBindTexture (GL_TEXTURE_2D, active_texture);
}
+static void
+gdk_gl_texture_do_download_float (GdkTexture *texture,
+ float *data)
+{
+ GdkGLTexture *self = GDK_GL_TEXTURE (texture);
+ int active_texture;
+
+ gdk_gl_context_make_current (self->context);
+
+ glGetIntegerv (GL_TEXTURE_BINDING_2D, &active_texture);
+ glBindTexture (GL_TEXTURE_2D, self->id);
+
+ glGetTexImage (GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ GL_FLOAT,
+ data);
+
+ glBindTexture (GL_TEXTURE_2D, active_texture);
+}
+
+static void
+gdk_gl_texture_download_float (GdkTexture *texture,
+ float *data,
+ gsize stride)
+{
+ GdkGLTexture *self = GDK_GL_TEXTURE (texture);
+ int width, height, y;
+ float *copy;
+
+ if (self->saved)
+ {
+ gdk_texture_download_float (self->saved, data, stride);
+ return;
+ }
+
+ width = gdk_texture_get_width (texture);
+ height = gdk_texture_get_height (texture);
+
+ if (stride == width * 4)
+ {
+ gdk_gl_texture_do_download_float (texture, data);
+ return;
+ }
+
+ copy = g_new (float, width * height * 4);
+
+ gdk_gl_texture_do_download_float (texture, copy);
+ for (y = 0; y < height; y++)
+ memcpy (data + y * stride, copy + y * 4 * width, 4 * width);
+
+ g_free (copy);
+}
+
static void
gdk_gl_texture_class_init (GdkGLTextureClass *klass)
{
texture_class->download_texture = gdk_gl_texture_download_texture;
texture_class->download = gdk_gl_texture_download;
+ texture_class->download_float = gdk_gl_texture_download_float;
gobject_class->dispose = gdk_gl_texture_dispose;
}
gdk_texture_get_height (texture));
}
+static void
+gdk_memory_texture_download_float (GdkTexture *texture,
+ float *data,
+ gsize stride)
+{
+ GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
+
+ gdk_memory_convert_to_float (data, stride,
+ (guchar *) g_bytes_get_data (self->bytes, NULL),
+ self->stride,
+ self->format,
+ gdk_texture_get_width (texture),
+ gdk_texture_get_height (texture));
+}
+
static void
gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
{
texture_class->download_texture = gdk_memory_texture_download_texture;
texture_class->download = gdk_memory_texture_download;
+ texture_class->download_float = gdk_memory_texture_download_float;
gobject_class->dispose = gdk_memory_texture_dispose;
}
converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
}
+
+#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\
+ for (y = 0; y < height; y++) \
+ { \
+ for (x = 0; x < width; x++) \
+ { \
+ if (A >= 0) \
+ { \
+ dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \
+ dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \
+ dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \
+ dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \
+ if (premultiply) \
+ { \
+ dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \
+ dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \
+ dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \
+ } \
+ } \
+ else \
+ { \
+ dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \
+ dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \
+ dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \
+ dest_data[4 * x + 3] = 1.0; \
+ } \
+ } \
+\
+ dest_data += dest_stride; \
+ src_data += src_stride; \
+ } \
+}G_STMT_END
+
+void
+gdk_memory_convert_to_float (float *dest_data,
+ gsize dest_stride,
+ const guchar *src_data,
+ gsize src_stride,
+ GdkMemoryFormat src_format,
+ gsize width,
+ gsize height)
+{
+ gsize x, y;
+
+ switch (src_format)
+ {
+ case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
+ CONVERT_FLOAT (2, 1, 0, 3, FALSE);
+ break;
+ case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
+ CONVERT_FLOAT (1, 2, 3, 0, FALSE);
+ break;
+ case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
+ CONVERT_FLOAT (0, 1, 2, 3, FALSE);
+ break;
+ case GDK_MEMORY_B8G8R8A8:
+ CONVERT_FLOAT (2, 1, 0, 3, TRUE);
+ break;
+ case GDK_MEMORY_A8R8G8B8:
+ CONVERT_FLOAT (1, 2, 3, 0, TRUE);
+ break;
+ case GDK_MEMORY_R8G8B8A8:
+ CONVERT_FLOAT (0, 1, 2, 3, TRUE);
+ break;
+ case GDK_MEMORY_A8B8G8R8:
+ CONVERT_FLOAT (3, 2, 1, 0, TRUE);
+ break;
+ case GDK_MEMORY_R8G8B8:
+ CONVERT_FLOAT (0, 1, 2, -1, FALSE);
+ break;
+ case GDK_MEMORY_B8G8R8:
+ CONVERT_FLOAT (2, 1, 0, -1, FALSE);
+ break;
+
+ case GDK_MEMORY_N_FORMATS:
+ default:
+ g_assert_not_reached();
+ }
+}
gsize width,
gsize height);
+void gdk_memory_convert_to_float (float *dest_data,
+ gsize dest_stride,
+ const guchar *src_data,
+ gsize src_stride,
+ GdkMemoryFormat src_format,
+ gsize width,
+ gsize height);
+
G_END_DECLS
g_object_unref (memory_texture);
}
+static void
+gdk_texture_real_download_float (GdkTexture *self,
+ float *data,
+ gsize stride)
+{
+ GdkTexture *memory_texture;
+
+ memory_texture = gdk_texture_download_texture (self);
+ gdk_texture_download_float (memory_texture, data, stride);
+ g_object_unref (memory_texture);
+}
+
static void
gdk_texture_set_property (GObject *gobject,
guint prop_id,
klass->download_texture = gdk_texture_real_download_texture;
klass->download = gdk_texture_real_download;
+ klass->download_float = gdk_texture_real_download_float;
gobject_class->set_property = gdk_texture_set_property;
gobject_class->get_property = gdk_texture_get_property;
GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride);
}
+/**
+ * gdk_texture_download_float:
+ * @texture: a `GdkTexture`
+ * @data: (array): pointer to enough memory to be filled with the
+ * downloaded data of @texture
+ * @stride: rowstride in elements, will usually be equal to
+ * gdk_texture_get_width() * 4
+ *
+ * Downloads the @texture into local memory in a high dynamic range format.
+ *
+ * This may be an expensive operation, as the actual texture data
+ * may reside on a GPU or on a remote display server and because the data
+ * may need to be upsampled if it was not already available in this
+ * format.
+ *
+ * You may want to use [method@Gdk.Texture.download] instead if you don't
+ * need high dynamic range support.
+ *
+ * The data format of the downloaded data is equivalent to
+ * GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, so every downloaded
+ * pixel requires 16 bytes of memory.
+ *
+ * Note that the caller is responsible to provide sufficiently
+ * aligned memory to access the resulting data directly as floats.
+ *
+ * Since: 4.6
+ */
+void
+gdk_texture_download_float (GdkTexture *texture,
+ float *data,
+ gsize stride)
+{
+ g_return_if_fail (GDK_IS_TEXTURE (texture));
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
+
+ GDK_TEXTURE_GET_CLASS (texture)->download_float (texture, data, stride);
+}
+
GdkTexture *
gdk_texture_download_texture (GdkTexture *texture)
{
void gdk_texture_download (GdkTexture *texture,
guchar *data,
gsize stride);
+GDK_AVAILABLE_IN_4_6
+void gdk_texture_download_float (GdkTexture *texture,
+ float *data,
+ gsize stride);
GDK_AVAILABLE_IN_ALL
gboolean gdk_texture_save_to_png (GdkTexture *texture,
const char *filename);
void (* download) (GdkTexture *texture,
guchar *data,
gsize stride);
+ void (* download_float) (GdkTexture *texture,
+ float *data,
+ gsize stride);
};
gpointer gdk_texture_new (const GdkTextureClass *klass,